package com.cal.utms.util;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class ValueConvert {

	public static BigDecimal toBigDecimal(Object object) {
		if (object == null) {
			return null;
		} else if (object instanceof BigDecimal) {
			return (BigDecimal) object;
		} else if (object instanceof String) {
			if ("null".equals(object))
				return null;
			return new BigDecimal((String) object);
		} else if (object instanceof Number) {
			return new BigDecimal(((Number) object).doubleValue());
		} else {
			throw new ClassCastException("Unable to cast '" + object + "' from " + object.getClass() + " to " + BigDecimal.class);
		}
	}

	public static Float toFloat(Object object) {

		if (object == null) {
			return null;
		} else if (object instanceof Float) {
			return (Float) object;
		} else if (object instanceof Float) {
			return new Float((String) object);
		} else if (object instanceof Number) {
			return ((Number) object).floatValue();
		} else {
			throw new ClassCastException("Unable to cast '" + object + "' from " + object.getClass() + " to " + Float.class);
		}
	}

	public static Long toLong(Object object) {
		if (object == null) {
			return null;
		} else if (object instanceof Long) {
			return (Long) object;
		} else if (object instanceof String) {
			return new Long((String) object);
		} else if (object instanceof Number) {
			return ((Number) object).longValue();
		} else {
			throw new ClassCastException("Unable to cast '" + object + "' from " + object.getClass() + " to " + Long.class);
		}
	}

	public static Integer toInteger(Object object) {
		if (object == null) {
			return null;
		} else if (object instanceof Integer) {
			return (Integer) object;
		} else if (object instanceof String) {
			return new Integer((String) object);
		} else if (object instanceof Number) {
			return ((Number) object).intValue();
		} else {
			throw new ClassCastException("Unable to cast '" + object + "' from " + object.getClass() + " to " + Integer.class);
		}
	}

	public static Short toShort(Object object) {
		if (object == null) {
			return null;
		} else if (object instanceof Short) {
			return (Short) object;
		} else if (object instanceof String) {
			return new Short((String) object);
		} else if (object instanceof Number) {
			return ((Number) object).shortValue();
		} else {
			throw new ClassCastException("Unable to cast '" + object + "' from " + object.getClass() + " to " + Short.class);
		}
	}

	public static Date toDate(Object object) {
		if (object == null) {
			return null;
		} else if (object instanceof Date) {
			return (Date) object;
		} else if (object instanceof String) {
			return string2date((String) object);
		} else if (object instanceof Long) {
			return new Date((Long) object);
		} else {
			throw new ClassCastException("Unable to cast '" + object + "' from " + object.getClass() + " to " + Date.class);
		}
	}

	public static Character toCharacter(Object object) {
		if (object == null) {
			return null;
		} else if (object instanceof Character) {
			return (Character) object;
		} else if (object instanceof String && ((String) object).length() == 1) {
			return ((String) object).charAt(0);
		} else if (object instanceof Short) {
			return new Character((char) ((Short) object).shortValue());
		} else if (object instanceof Integer) {
			return new Character((char) ((Integer) object).intValue());
		} else {
			throw new ClassCastException("Unable to cast '" + object + "' from " + object.getClass() + " to " + Character.class);
		}
	}

	public static Boolean toBoolean(Object object) {
		if (object == null) {
			return null;
		} else if (object instanceof Boolean) {
			return (Boolean) object;
		} else if (object instanceof String && ((String) object).length() == 1) {
			return Boolean.parseBoolean((String) object);
		} else if (object instanceof Number) {
			return ((Number) object).intValue() > 0;
		} else {
			throw new ClassCastException("Unable to cast '" + object + "' from " + object.getClass() + " to " + Character.class);
		}
	}

	public static Date string2date(String date) {
		if (date == null)
			return null;
		if (date.length() < 12) {
			int year = Integer.parseInt(date.substring(0, date.indexOf('-'))) - 1900;
			int month = Integer.parseInt(date.substring(date.indexOf('-') + 1, date.lastIndexOf('-'))) - 1;
			int day = Integer.parseInt(date.substring(date.lastIndexOf('-') + 1));
			return new Date(year, month, day);
		}
		int year = Integer.parseInt(date.substring(0, date.indexOf('-'))) - 1900;
		int month = Integer.parseInt(date.substring(date.indexOf('-') + 1, date.lastIndexOf('-'))) - 1;
		int day = Integer.parseInt(date.substring(date.lastIndexOf('-') + 1, date.indexOf(' ')));
		int hour = Integer.parseInt(date.substring(date.indexOf(' ') + 1, date.indexOf(':')));
		int minute = Integer.parseInt(date.substring(date.indexOf(':') + 1, date.lastIndexOf(':')));
		int second = Integer.parseInt(date.substring(date.lastIndexOf(':') + 1));
		return new Date(year, month, day, hour, minute, second);
	}

	final static String[] basic = { "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen",
			"Sixteen", "Seventeen", "Eighteen", "Nineteen" };

	final static String[] ziroToNine = { "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" };

	final static String[] decs = { "", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety" };

	public static String[] csv2Array(String csv) {
		if (csv == null) {
			return null;
		}
		List<String> arrayList = new ArrayList<String>();
		int indexOfComma = csv.indexOf(',');
		while (indexOfComma >= 0) {
			arrayList.add(csv.substring(0, indexOfComma));
			csv = csv.substring(indexOfComma + 1);
			indexOfComma = csv.indexOf(',');
		}
		return arrayList.toArray(new String[0]);
	}

	public static String numbersToCurrencyWord(BigDecimal numberValue) {
		// numberValue = formatNumberToCurrency(numberValue).doubleValue();

		String stringValue = numberValue.toString();
		BigInteger decimalValue;
		BigInteger intigerValue;

		if (stringValue.indexOf(".") > 0)
			stringValue += "00";
		else
			stringValue += ".00";

		decimalValue = new BigInteger(stringValue.substring(stringValue.indexOf(".") + 1, stringValue.indexOf(".") + 5));

		intigerValue = numberValue.toBigInteger();
		/*
		 * System.out.println(intval); System.out.println(decimal);
		 */

		if (decimalValue.intValue() > 0)
			return convertTocurrencyText(intigerValue) + " point " + convertToDecimalText(decimalValue);
		else
			return convertTocurrencyText(intigerValue);

	}

	private static String convertToDecimalText(BigInteger decimalValue) {
		String number = decimalValue.toString();
		String[] s = number.split("");

		String word = null;
		for (int i = 1; i < s.length; i++) {
			if (word == null) {
				word = ziroToNine[Integer.parseInt(s[i])];
			} else {
				word = word.concat(" " + ziroToNine[Integer.parseInt(s[i])]);
			}
		}

		return word;
	}

	private static String convertTocurrencyText(BigInteger numberValue) {
		if (numberValue.compareTo(new BigInteger("20")) == -1)
			return basic[numberValue.intValue()];
		else if (numberValue.compareTo(new BigInteger("100")) == -1)
			return decs[numberValue.divide(new BigInteger("10")).intValue()]
					+ ((numberValue.intValue() % 10 > 0) ? " " + convertTocurrencyText(numberValue.mod(new BigInteger("10"))) : "");
		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 3))) == -1) {
			return basic[numberValue.divide(new BigInteger("100")).intValue()] + " Hundred and"
					+ ((numberValue.mod(new BigInteger("100")).compareTo(BigInteger.ZERO) == 1) ? " " + convertTocurrencyText((numberValue.mod(new BigInteger("100")))) : "");

		} else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 6))) == -1)
			return convertTocurrencyText(numberValue.divide(new BigInteger("1" + padRight("0", 3))))
					+ " Thousand, "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 3))).compareTo(BigInteger.ZERO) == 1) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 3))))) : "");

		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 9))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 6)))))
					+ " Million, "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 6))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 6))))) : "");

		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 12))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 9)))))
					+ " Billion, "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 9))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 9))))) : "");
		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 15))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 12)))))
					+ " Trillion, "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 12))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 12))))) : "");

		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 18))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 15)))))
					+ " Quadrillion, "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 15))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 15))))) : "");
		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 21))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 18)))))
					+ " Quintillion, "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 18))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 18))))) : "");
		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 24))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 21)))))
					+ " Sextillion, "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 21))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 21))))) : "");

		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 27))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 24)))))
					+ " Septillion, "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 24))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 24))))) : "");

		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 30))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 27)))))
					+ " Octillion, "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 27))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 27))))) : "");

		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 33))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 30)))))
					+ " Nonillion, "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 30))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 30))))) : "");

		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 36))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 33)))))
					+ " Decillion, "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 33))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 33))))) : "");

		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 39))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 36)))))
					+ " Undecillion, "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 36))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 36))))) : "");

		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 42))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 39)))))
					+ " Duodecillion "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 39))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 39))))) : "");
		else if (numberValue.compareTo(new BigInteger("1" + padRight("0", 45))) == -1)
			return convertTocurrencyText((numberValue.divide(new BigInteger("1" + padRight("0", 42)))))
					+ " Tredecillion "
					+ ((numberValue.mod(new BigInteger("1" + padRight("0", 42))).compareTo(BigInteger.ZERO) > 0) ? " "
							+ convertTocurrencyText((numberValue.mod(new BigInteger("1" + padRight("0", 42))))) : "");

		return null;
	}

	public static String padRight(String s, int n) {

		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < n; i++) {
			stringBuilder.append(s);
		}
		return stringBuilder.toString();

	}
}
